国际化:i18n 插件使用中坑点(JS & TS 是只读的)
语言切换的 UI 实现
使用 Element Plus 的 Dropdown 组件实现语言切换:
<template>
<el-dropdown @command="handleCommand">
<span class="language-switch">
{{ currentLabel }}
<el-icon><ArrowDown /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="zh-CN">中文</el-dropdown-item>
<el-dropdown-item command="en">English</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { ArrowDown } from '@element-plus/icons-vue'
import { loadLocaleMessages } from '@/modules/i18n'
const currentLocale = computed(() => {
// 获取当前语言
})
const currentLabel = computed(() => {
return currentLocale.value === 'zh-CN' ? '中文' : 'English'
})
function handleCommand(lang: string) {
loadLocaleMessages(lang)
}
</script>
vue
不需要在 components 目录下创建专门的 Translation 组件,直接使用 Element Plus 提供的基础组件即可。
核心坑点:JS/TS 文件是只读的
问题说明
i18n Ally 插件不支持反向写入 .js 或 .ts 后缀的翻译文件。原因:
- JS/TS 太过动态,无法安全地进行反向操作(从翻译键值反向写入文件)
- 插件无法确定 JS/TS 文件的导出结构是否安全修改
- 官方明确不支持对
.js/.ts文件执行"提取文案到 i18n"的反向写入操作
两种使用场景的选择
| 场景 | 推荐格式 | 原因 |
|---|---|---|
| 固定字段少(如 Element Plus) | .js / .ts | 保留语法提示、动态消息能力 |
| 业务功能多 | .json | 支持 i18n Ally 反向写入和自动翻译 |
切换到 JSON 格式
1. 重命名文件
locales/
├── zh-CN.js → zh-CN.json
└── en.js → en.json
text
2. 更新文件内容格式
// locales/zh-CN.json
{
"hello": "你好,我是 mock"
}
json
// locales/en.json
{
"hello": "Hello, I am mock"
}
json
3. 更新 i18n 模块中的 glob 匹配
// src/modules/i18n.ts
// 将 glob 模式从 .js 改为 .json
const localesMap = Object.fromEntries(
Object.entries(
import.meta.glob('../../locales/*.json', { eager: true })
).map(([path, loadLocale]) => {
const localeKey = path.match(/\/([^/]+)\.json$/)?.[1] || ''
return [localeKey, loadLocale]
})
) as Record<string, { default: Record<string, string> }>
// Element Plus 部分保持 .mjs 不变
typescript
4. 更新 VS Code 配置
// .vscode/settings.json
{
"i18n-ally.localesPaths": ["locales"],
"i18n-ally.enabledParsers": ["json"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN"
}
json
i18n Ally 插件使用流程
提取文案
- 在代码中选中需要翻译的字符串
- 按快捷键
Cmd + .(Mac)或Ctrl + .(Windows) - 选择"提取文案到 i18n"
如果快捷键没有弹出菜单,可以通过命令面板:
Cmd/Ctrl + Shift + P打开命令面板- 输入
i18n找到"提取文案"选项
创建嵌套路径
在提取文案时可以创建嵌套的 JSON 结构:
输入路径:anything.thing.next1.next2
生成的 JSON:
{
"anything": {
"thing": {
"next1": {
"next2": "翻译内容"
}
}
}
}
text
翻译缺失文案
i18n Ally 的侧边栏会显示翻译进度和缺失项:
- 编辑
en.json填入英文翻译 - 点击侧边栏的国际化图标(地球)
- 选择目标语言自动翻译
- 翻译完成后
zh-CN.json自动填入对应内容
翻译引擎配置
i18n Ally 支持多种翻译 API,在 VS Code 设置中配置:
// .vscode/settings.json
{
"i18n-ally.translate.engines": ["deepl", "openai", "google"],
// DeepL 配置
"i18n-ally.deepl.apiKey": "your-deepl-api-key",
"i18n-ally.deepl.useFreeApiEntry": true,
// OpenAI 配置
"i18n-ally.openai.apiKey": "your-openai-api-key",
"i18n-ally.openai.model": "gpt-4o-mini",
"i18n-ally.openai.apiBase": "https://your-proxy-url/v1",
// 百度翻译配置(国内可用)
"i18n-ally.baidu.appid": "your-appid",
"i18n-ally.baidu.key": "your-key"
}
json
翻译引擎推荐
| 引擎 | 翻译质量 | 国内可达 | 成本 |
|---|---|---|---|
| DeepL | 最高 | 需代理 | 免费 50 万字符/月 |
| OpenAI | 高,可定制 | 需代理/镜像 | 极低 |
| 百度翻译 | 良好 | 直接可用 | 免费 5 万字符/月 |
| 良好 | 需代理 | 有限免费 |
国内开发者推荐使用百度翻译作为默认引擎,避免代理问题。有条件的可使用 DeepL 获得更高质量。
国内翻译 API 申请参考
| API | 免费额度 | 申请地址 |
|---|---|---|
| 百度翻译 | 5 万字符/月(标准) | https://fanyi-api.baidu.com |
| 有道翻译 | 1000 字/天 | https://ai.youdao.com |
| 腾讯翻译君 | 500 万字符/月 | https://cloud.tencent.com/product/tmt |
| DeepL | 50 万字符/月 | https://www.deepl.com/pro-api |
项目配置注意事项
切换到 JSON 格式后,确保以下位置同步更新:
1. 文件后缀:locales/*.js → locales/*.json
2. glob 模式:import.meta.glob('../../locales/*.json', ...)
3. VS Code 设置:enabledParsers 包含 "json"
4. 翻译文件格式:从 export default {} → 纯 JSON 对象
5. 重启 VS Code 扩展宿主使配置生效
text
总结
- JS/TS 格式的翻译文件不支持 i18n Ally 反向写入,只读
- 固定字段少的场景(如组件库)适合用 JS/TS,业务项目推荐 JSON
- JSON 格式配合 i18n Ally 可实现:提取文案 → 自动翻译 → 写入文件
- i18n Ally 支持 DeepL、OpenAI、百度、Google 等翻译引擎
- 国内推荐百度翻译(直接可用),追求质量选 DeepL
- 切换格式后需同步更新 glob 模式和 VS Code 配置
↑